<template>
	<view class="vk-uni-pay"></view>
</template>

<script>
var intervalID;
import vkUtil from "./js_sdk/vk-util.js";
export default {
	name: "vk-uni-pay",
	emits: ["update:status", "update:codeUrl", "update", "success", "fail", "cancel"],
	props: {
		/**
		 * 查询支付订单的云函数
		 * :query-payment-action="vkPay.queryPaymentAction"
		 */
		queryPaymentAction: {
			Type: [Object, String],
			default() {
				return {
					name: "vk-pay",
					action: "pay/queryPayment",
					actionKey: "action",
					dataKey: "data"
				};
			}
		},
		/**
		 * PC支付的付款二维码地址
		 * :code-url.sync="vkPay.codeUrl"
		 */
		codeUrl: {
			Type: String
		},
		/**
		 * 0:等待发起支付 1:支付中 2:已支付
		 * :status.sync="vkPay.status"
		 */
		status: {
			Type: Number,
			default: 0
		},
		/**
		 * 当前页面是否是显示状态，主要用于配合polling使用
		 * :page-show="vkPay.pageShow"
		 */
		pageShow: {
			Type: Boolean,
			default: true
		},
		/**
		 * 启用轮询检测订单支付状态（仅h5支付有效）
		 * :polling="vkPay.polling"
		 */
		polling: {
			Type: Boolean,
			default: false
		},
		/**
		 * 轮询间隔
		 * :polling-time="vkPay.pollingTime"
		 */
		pollingTime: {
			Type: [Number, String],
			default: 1000
		},
		/**
		 * 仅微信手机外部浏览器H5支付时有效
		 * :return-url="vkPay.returnUrl"
		 */
		returnUrl: {
			Type: String
		}
	},
	data: function() {
		// 组件创建时,进行数据初始化
		return {
			// 当前平台
			platform: "other",
			// 表单提交的数据
			form1: {
				openid: "",
				out_trade_no: "",
				isPC: false // 当前是否是电脑访问
			}
		};
	},
	mounted() {
		this.init();
	},
	// #ifndef VUE3
	destroyed() {
		if (intervalID) clearInterval(intervalID);
	},
	// #endif
	// #ifdef VUE3
	unmounted() {
		if (intervalID) clearInterval(intervalID);
	},
	// #endif
	methods: {
		// 初始化
		init() {
			let that = this;
			// #ifdef APP-PLUS
			that.platform = "app";
			// #endif
			// #ifdef H5
			that.platform = "h5";
			that.form1.isPC = vkUtil.checkPlatform() == "pc" ? true : false;
			// #endif
			// #ifdef MP-WEIXIN
			that.platform = "mp-weixin";
			// #endif
			// #ifdef MP-ALIPAY
			that.platform = "mp-alipay";
			// #endif
			that.getOpenid();
		},
		// 获取openid(小程序支付需要openid)
		getOpenid() {
			let that = this;
			return new Promise((resolve, reject) => {
				if (that.form1.openid) {
					resolve();
				} else {
					vkUtil
						.getOpenid()
						.then(res => {
							that.form1.openid = res.openid;
							resolve(res);
						})
						.catch(res => {
							reject(res);
						});
				}
			});
		},
		/**
		 * 发起支付
		 * provider		支付供应商
		 * total_fee		支付金额 单位分 100 = 1元
		 * out_trade_no	支付订单号
		 * subject		订单标题
		 * body				订单内容
		 */
		createPayment(obj = {}) {
			let that = this;
			let { form1 } = that;
			let { needAlert=false } = obj;
			form1 = Object.assign(form1, obj.data);
			that.$emit("update:status", 0);
			uni.showLoading({ title: "请求中..." });
			that.getOpenid().then(() => {
				vkUtil.callFunction({
					action: obj.action,
					data: form1,
					needAlert,
					success: function(res) {
						if (that.platform == "h5" || (form1.alipayAppPayToH5Pay && that.platform == "app" && form1.provider == "alipay")) {
							that._h5Pay(res, obj);
						} else if (that.platform == "app") {
							that._appPay(res, obj);
						} else if (that.platform == "mp-weixin") {
							that._mpWxPay(res, obj);
						} else if (that.platform == "mp-alipay") {
							that._mpAliPay(res, obj);
						} else {
							vkUtil.alert("暂不支持该支付方式");
							return false;
						}
						that.$emit("update:status", 1);
					},
					fail: function(err) {
						let errObj = {
							...err,
							failType: "create",
							failTypeMsg: "创建支付失败"
						};
						that.$emit("fail", errObj);
						if (typeof obj.fail === "function") obj.fail(errObj);
					},
					complete: function() {
						uni.hideLoading();
					}
				});
			});
		},
		// 支付状态查询
		queryPayment(obj = {}) {
			let that = this;
			vkUtil.callFunction({
				action: that.queryPaymentAction,
				data: obj.data,
				title: obj.title,
				needAlert: obj.needAlert,
				success: function(res) {
					if (obj.success) obj.success(res);
				},
				fail: function(res) {
					if (obj.fail) obj.fail(res);
				},
				complete: function(res) {
					if (obj.complete) obj.complete(res);
				}
			});
		},
		/////////////////////////////以下为内部方法//////////////////////////////
		// h5支付
		_h5Pay(res, obj) {
			let that = this;
			let { form1, returnUrl } = that;
			let codeUrl = res.orderInfo.codeUrl;
			let mwebUrl = res.orderInfo.mwebUrl || res.orderInfo.mweb_url;
			if (codeUrl) {
				// 二维码支付
				// 判断是否在手机环境，如果是，则直接访问二维码地址
				if (that.polling) {
					that._checkPay(res.out_trade_no, obj.success);
				}
				if (that.form1.isPC || (form1.provider == "wxpay" && codeUrl)) {
					// pc环境 或 微信H5支付 建议用扫一扫而不要用手机长按识别功能,容易被微信判定为异常订单
					that.$emit("update:codeUrl", codeUrl);
				} else {
					setTimeout(function() {
						// 手机环境且是支付宝 支付宝在非微信浏览器中会自动跳转到支付宝APP中付款
						if (that.platform == "app") {
							plus.runtime.openURL(codeUrl);
						} else {
							window.location.href = codeUrl || mwebUrl;
						}
					}, 300);
				}
			} else if (mwebUrl) {
				// 微信手机外部浏览器支付
				if (!returnUrl) returnUrl = window.location.href;
				let urlParamObj = vkUtil.urlToObject(returnUrl);
				urlParamObj.confirmShow = true;
				urlParamObj.out_trade_no = form1.out_trade_no;
				let url = returnUrl.split("?")[0] + vkUtil.objectToUrl(urlParamObj);
				mwebUrl += "&redirect_url=" + encodeURIComponent(url);
				setTimeout(function() {
					if (that.platform == "app") {
						plus.runtime.openURL(mwebUrl);
					} else {
						window.location.href = mwebUrl;
					}
				}, 300);
			} else {
				// 微信公众号支付
				// #ifdef H5
				WeixinJSBridge.invoke("getBrandWCPayRequest", res.orderInfo, function(res) {
					if (res.err_msg == "get_brand_wcpay_request:ok") {
						// 用户支付成功回调
						if (typeof obj.success === "function") obj.success(res);
					} else if (res.err_msg == "get_brand_wcpay_request:cancel") {
						// 用户取消支付回调
						if (typeof obj.cancel === "function") obj.cancel(res);
					} else if (res.err_msg == "get_brand_wcpay_request:fail") {
						// 用户支付失败回调
						if (typeof obj.fail === "function") obj.fail(res);
					}
					// 无论成功或失败或取消均会触发的回调
					if (typeof obj.complete === "function") obj.complete(res);
				});
				// #endif
			}
		},
		// app支付
		_appPay(res, obj) {
			let that = this;
			let { form1 } = that;
			let { out_trade_no } = res;
			uni.requestPayment({
				provider: form1.provider,
				orderInfo: res.orderInfo,
				...res.orderInfo,
				success() {
					that._checkPay(out_trade_no, obj.success, "请稍等...");
				},
				fail(err) {
					console.error(err);
					vkUtil.toast("发起支付失败");
				}
			});
		},
		// 微信小程序支付
		_mpWxPay(res, obj) {
			let that = this;
			let { out_trade_no } = res;
			uni.requestPayment({
				...res.orderInfo,
				success() {
					that._checkPay(out_trade_no, obj.success, "请稍等...");
				},
				fail(err) {
					if (err.errMsg.indexOf("fail cancel") == -1) {
						console.error(err);
						let errObj = {
							...err,
							failType: "request",
							failTypeMsg: "请求支付失败"
						};
						that.$emit("fail", errObj);
						if (typeof obj.fail === "function") obj.fail(errObj);
					} else {
						that.$emit("cancel", err);
						if (typeof obj.cancel === "function") obj.cancel(err);
					}
				}
			});
		},
		// 支付宝小程序支付
		_mpAliPay(res, obj) {
			let that = this;
			let { out_trade_no } = res;
			uni.requestPayment({
				orderInfo: res.orderInfo,
				success() {
					that._checkPay(out_trade_no, obj.success, "请稍等...");
				},
				fail(err) {
					if (err.errMsg.indexOf("fail cancel") == -1) {
						console.error(err);
						let errObj = {
							...err,
							failType: "request",
							failTypeMsg: "请求支付失败"
						};
						that.$emit("fail", errObj);
						if (typeof obj.fail === "function") obj.fail(errObj);
					} else {
						that.$emit("cancel", err);
						if (typeof obj.cancel === "function") obj.cancel(err);
					}
				}
			});
		},
		// 检测支付状态
		_checkPay(out_trade_no, success, title) {
			let that = this;
			// 立刻检测一次，如果通过，则无需执行后面的轮询。
			setTimeout(function() {
				that._queryPayment(out_trade_no, success, function(res) {
					// 轮询检测支付状态，写轮询是为了避免特殊情况的发生。
					if (title) uni.showLoading({ title });
					let num = 0;
					if (intervalID) clearInterval(intervalID);
					intervalID = setInterval(function() {
						if (that.pageShow) {
							num++;
							if (num > 120 || that.status != 1) {
								if (title) uni.hideLoading();
								clearInterval(intervalID);
							} else {
								that._queryPayment(out_trade_no, success);
							}
						} else {
							// console.log("当前页面未显示,不执行本次轮询");
						}
					}, Number(that.pollingTime));
				});
			}, 200);
		},
		// 支付状态查询
		_queryPayment(out_trade_no, success, fn) {
			let that = this;
			vkUtil.callFunction({
				action: that.queryPaymentAction,
				data: {
					out_trade_no
				},
				needAlert: false,
				success: function(res) {
					uni.hideLoading();
					if (intervalID) clearInterval(intervalID);
					that.$emit("update:status", 2);
					that.$emit("success", res);
					if (typeof success === "function") success(res);
				},
				fail: function() {
					if (fn) fn();
				}
			});
		}
		/////////////////////////////以上为内部方法//////////////////////////////
	},
  // 监听属性
  watch: {},
	// 计算属性
	computed: {}
};
</script>

<style lang="scss" scoped></style>
